// GBT-36624-10
#pragma once
#include "../../common/include/obj.h"
#include "ecb_mode.h"

class C_GCM_MODE : public CVirtualDestruct
{
public:
    C_GCM_MODE();

    virtual int Init(BYTE *pIV, int iIV, BYTE *pAAD, int iAAD, IBlockCipherKernel *pobjKer);
    virtual int Encrypt(BYTE *pIn, int iLenIn, BYTE *pOut, int *piLenOut); // pIn为空表示计算校验值
    virtual int Decrypt(BYTE *pIn, int iLenIn, BYTE *pOut, int *piLenOut);
    /* pIn为空表示计算校验值
    解密不输入校验值
    */

protected:
    IBlockCipherKernel *m_pobjKer = nullptr;

    BYTE m_bfH[16];
    BYTE m_bfX[16];
    BYTE m_bfY[16];
    BYTE m_bfY0[16]; // Y0的密文

    U64 m_u64W; // AAD长度。单位比特。
    U64 m_u64Z; // IV长度或已计算的密文长度。单位比特。

    STD_BUFFER m_bufCache;

    virtual int InitG(BYTE *data = nullptr, int iLen = 0);
    /*初始化G函数
    data    W参数
    iLen    W参数长度
    说明：一次加/解密需要初始化2次G函数。第1次计算IV，W为空；第2次计算校验值，W为AAD。
    */

    virtual int UpdateG(BYTE *data, int iLen, int bW = 0);
    virtual int FinishG(OUT BYTE *data);
    virtual int Encrypt(BYTE *pIn, BYTE *pOut);
    virtual int Decrypt(BYTE *pIn, BYTE *pOut);
    virtual int IncY();
};
